<template>
  <el-menu
    :default-active="activeMenu"
    mode="horizontal"
    @select="handleSelect"
  >
    <template v-for="(item, index) in topMenus">
      <el-menu-item
        v-if="index < visibleNumber"
        :key="index"
        :index="item.path"
      >
        <item
          v-if="item.meta"
          :icon="item.meta.icon"
          :title="item.meta.title"
        />
      </el-menu-item>
    </template>

    <!-- 顶部菜单超出数量折叠 -->
    <el-submenu v-if="topMenus.length > visibleNumber" index="more">
      <template slot="title">更多菜单</template>
      <template v-for="(item, index) in topMenus">
        <el-menu-item
          v-if="index >= visibleNumber"
          :key="index"
          :index="item.path"
          class="top-menu-item"
        >
          <item
            v-if="item.meta"
            :icon="item.meta.icon"
            :title="item.meta.title"
          />
        </el-menu-item>
      </template>
    </el-submenu>
  </el-menu>
</template>

<script>
import Item from "@/layout/components/Sidebar/Item";
import { mapGetters, mapState } from "vuex";
import { isExternal } from "@/utils/validate";

export default {
  components: {
    Item,
  },
  data() {
    return {
      // 顶部栏初始数
      visibleNumber: 5,
      // 是否为首次加载
      isFristLoadIndex: true,
      sidebarOpenWidth: 0,
      sidebarCloseWidth: 0,
    };
  },
  computed: {
    ...mapGetters(["sidebar", "topbarRouters", "device", "defaultRoutes"]),
    ...mapState({
      topNav: (state) => state.settings.topNav,
    }),
    sidebarOpen() {
      return this.sidebar.opened;
    },
    // 顶部显示菜单
    topMenus() {
      return this.topbarRouters
        .filter((item) => {
          return !item.hidden && !this.isIndexPath(item.path);
        })
        .map((menu) => ({
          ...menu,
          children: undefined,
        }));
    },
    // 默认激活的菜单
    activeMenu() {
      const path = this.$route.path;
      this.activeRoutesHandle(path);
      return this.resolvePath(path);
    },
  },
  watch: {
    sidebarOpen(v) {
      this.setVisibleNumber(v);
    },
  },
  beforeMount() {
    window.addEventListener("resize", this.setVisibleNumber);
  },
  beforeDestroy() {
    window.removeEventListener("resize", this.setVisibleNumber);
  },
  mounted() {
    this.setVisibleNumber();
  },
  methods: {
    // 根据宽度计算设置显示栏数
    setVisibleNumber(sidebarOperate = null) {
      // 计算显示个数，无法适配任意屏幕大小，始终会存在右边内容被遮挡问题。
      // const width = document.body.getBoundingClientRect().width - 50
      // const sidebarContainerWidth =
      //   sidebarOperate === null
      //     ? document.getElementById('sidebar-container').getBoundingClientRect()
      //       .width
      //     : sidebarOperate
      //       ? 250
      //       : this.device === 'mobile'
      //         ? 0
      //         : 54
      // const rightMenuWidth = document
      //   .getElementById('right-menu')
      //   .getBoundingClientRect().width
      // const menuItemNodes = this.$el.children
      // const menuItemNodeMaxWidth =
      //   menuItemNodes.length <= 1
      //     ? 75
      //     : Math.max(
      //       ...Array.from(menuItemNodes).map(
      //         i => i.getBoundingClientRect().width
      //       )
      //     )
      // const visibleNumber = Math.floor(
      //   (width - rightMenuWidth - sidebarContainerWidth) /
      //     Math.ceil(menuItemNodeMaxWidth)
      // )
      // this.visibleNumber =
      //   this.device === 'mobile' && !this.sidebarOpen
      //     ? visibleNumber - 1
      //     : visibleNumber
      const width = document.body.getBoundingClientRect().width / 3;
      this.visibleNumber = parseInt(width / 85);
    },
    // 菜单选择事件
    handleSelect(key) {
      if (key.indexOf("http://") !== -1 || key.indexOf("https://") !== -1) {
        // http(s):// 路径新窗口打开
        window.open(key, "_blank");
      } else if (key.indexOf("/redirect") !== -1) {
        // redirect 路径内部打开
        this.$router.push({ path: key.replace("/redirect", "") });
      } else {
        this.activeRoutesHandle(key, true, true);
      }
    },
    activeRoutesHandle(path, firstLayerRouter = false, isSelectHandle = false) {
      if (this.isIndexPath(path)) {
        if (this.isFristLoadIndex) {
          this.$store.commit(
            "SET_SIDEBAR_ROUTERS",
            this.defaultSecondaryRouter()
          );
        }
      } else {
        const secondaryRouter = this.findSecondaryRouter(
          this.topbarRouters,
          path,
          firstLayerRouter
        );
        if (isSelectHandle) {
          this.navigation(this.findDefaultRouter(secondaryRouter, path));
        }
        if (this.topNav) {
          if (
            secondaryRouter &&
            Array.isArray(secondaryRouter) &&
            secondaryRouter.length > 0
          ) {
            this.$store.commit("SET_SIDEBAR_ROUTERS", secondaryRouter);
          }
        } else {
          // 如果没有开启 topNav，需要重置 SIDEBAR_ROUTERS。
          this.$store.commit("SET_SIDEBAR_ROUTERS", this.defaultRoutes);
        }
      }
      this.isFristLoadIndex = false;
    },
    findDefaultRouter(secondaryRouter, path) {
      let defaultRouter;
      if (
        !secondaryRouter ||
        (Array.isArray(secondaryRouter) && secondaryRouter.length === 0)
      ) {
        defaultRouter = this.findFirstLevelRouter(path);
      } else {
        const visibleMenu = this.findVisibleMenu(secondaryRouter);
        defaultRouter = visibleMenu || this.findFirstLevelRouter(path);
      }
      return defaultRouter;
    },
    findFirstLevelRouter(path) {
      for (let item of this.topbarRouters) {
        if (item.path === path) {
          return item;
        }
      }
      return null;
    },
    findVisibleMenu(secondaryRouter) {
      for (let item of secondaryRouter) {
        let childrenVisibleMenu;
        if (!item.hidden) {
          if (Array.isArray(item.children) && item.children.length > 0) {
            childrenVisibleMenu = this.findVisibleMenu(item.children);
          }
          return childrenVisibleMenu ? childrenVisibleMenu : item;
        }
      }
    },
    navigation(router) {
      if (router) {
        const { meta, path } = router;
        if ((meta && meta.newTab) || isExternal(path)) {
          window.open(path, "_blank");
        } else {
          this.$router.push(path);
        }
      }
    },
    findSecondaryRouter(routers, path, firstLayerRouter = false) {
      let secondaryRouter = [];
      if (!this.isIndexPath(path)) {
        routers.forEach((item) => {
          if (item.path === path) {
            if (firstLayerRouter) {
              secondaryRouter = item.children;
            } else {
              secondaryRouter = routers;
            }
          } else if (Array.isArray(item.children) && item.children.length > 0) {
            const childSecond = this.findSecondaryRouter(item.children, path);
            if (childSecond.length > 0) {
              secondaryRouter = item.children;
            }
          }
        });
      }
      return secondaryRouter;
    },
    resolvePath(path) {
      if (this.isIndexPath(path)) {
        return path;
      } else {
        return this.resolveFirstLayerPath(path);
      }
    },
    resolveFirstLayerPath(path) {
      let firstLayerPath;
      const map = new Map();
      this.topbarRouters.forEach((item) => {
        const children = [];
        children.push(item.path);
        this.buildChildrenPath(item.children, children);
        map.set(item.path, children);
      });
      map.forEach((value, key) => {
        if (value.includes(path)) {
          firstLayerPath = key;
          return;
        }
      });
      return firstLayerPath;
    },
    buildChildrenPath(childrenData, children) {
      if (Array.isArray(childrenData) && childrenData.length > 0) {
        childrenData.forEach((item) => {
          children.push(item.path);
          if (Array.isArray(item.children) && item.children.length > 0) {
            this.buildChildrenPath(item.children, children);
          }
        });
      }
    },
    // 默认激活的路由
    defaultSecondaryRouter() {
      for (let i = 0; i < this.topbarRouters.length; i++) {
        if (
          !this.topbarRouters[i].hidden &&
          Array.isArray(this.topbarRouters[i].children) &&
          this.topbarRouters[i].children.length > 0 &&
          !this.isIndexPath(this.topbarRouters[i].path)
        ) {
          return this.topbarRouters[i].children;
        }
      }
      return [];
    },
    isIndexPath(path) {
      if (path === "/index" || path === "/" || path === "") {
        return true;
      } else {
        return false;
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.topmenu-container.el-menu--horizontal > .el-menu-item {
  float: left;
  height: 50px !important;
  line-height: 50px !important;
  padding: 0 0 !important;
  margin: 0 8px !important;
  i {
    margin-right: 4px;
  }
  svg {
    margin-right: 4px;
  }
}
.top-menu-item {
  i {
    margin-right: 4px;
  }
  svg {
    margin-right: 4px;
  }
}
.topmenu-container.el-menu--horizontal > .el-submenu {
  .el-submenu__title {
    padding: 0 8px;
  }
  .el-submenu__icon-arrow {
    margin-left: 2px;
  }
}
</style>
